fn main() {
  /** case1 error[E0425]: cannot find value `y` in this scope*/
  let x = 1; //是确定的类型, 为i32, 会分配到栈上
  { // y 在这里无效, 它尚未声明
    let y = 1; // 从此处起，y 是有效的
    println!("x = {}", x);
  } // 此作用域已结束，y 不再有效
  // println!("y = {}", y); //error[E0425]: cannot find value `y` in this scope

  /** case2: error[E0382]: borrow of moved value: `s1`*/
  // 见 README.md
  let mut s1 = String::from("hello"); // String类型, 在编译的时候并不能确定其大小, 会分配到堆上
  // s1.push_str(" world!");
  //String 类型离开作用域的时候(即声明时所处的`{}`的`}`) 会调用drop方法（释放内存）, 类似于C++里的析构函数

  let s2 = s1; //浅拷贝 拷贝的是地址, 并且在 rust中, 这里赋值完毕后, s1就无效了 （这是为了避免对同一块内存进行多次释放(drop)操作（这样会报错））
  // ↑ s1 的所有权 交给了 s2, s1丧失了所有权, 处于空的状态
  println!("{}",s2);
  // println!("{}",s1); //error[E0382]: borrow of moved value: `s1`
  //
  let s3 = s2.clone(); //深拷贝
  println!("{}", s3); //hello
  println!("{}", s2); //hello

  /** case3: 栈上的数据（基本类型数据(非引用类型)）不存在上面case2的问题*/
  //这是因为它实现了 copy trait
  let a = 1;
  let b = a;
  println!("a = {},b = {}",a,b);
  //
  /*
    trait
    美: [treɪt]
    英: [treɪt]
    n.	特点
    网络	特性；特征；特质
  */
  // 常用的具有 copy trait 的有:
  // 整形、浮点型、bool、字符类型(char)、turtle(元组)

  //3.2 数组
  let arr: [i32; 5] = [1, 2, 3, 4, 5];
  print_arr(arr);
  println!("{:?}", arr); // ← 并不会丧失所有权, arr是放在栈中的, 传给函数它会完全拷贝一份, 而不像其它语言一样给的是指针(引用)

  //3.3 元组
  let t1 = (1,'a',[1,2,3]/*,Stru123{name:"ahhh".to_string(),age:1000}*/);
  let t2 = t1;
  //如果 元组 里的成员不包含 引用类型(堆上的数据), 那么没的问题
  //但如果包含的话, 就会有所有权丧失问题
  println!("{:?}", t1); //(1, 'a', [1, 2, 3])
  println!("{:?}", t2); //(1, 'a', [1, 2, 3])

  /** case4: */
  let s = String::from("hello");
  take_ownership(s);
  // println!("{}",s); //error[E0382]: borrow of moved value: `s`

  let x = 1;
  make_copy(x);
  println!("{}", x); //1
}

fn take_ownership(some_string:String){
  println!("{}", some_string);
/*some_string会在此回收（外边的 s 给到我们这里的some_string后就已经变为空了） →*/}
fn make_copy(i:i32){
  println!("i = {}", i);
/*函数里的i在这里回收, 但并不影响函数外的（因为是基础类型） →*/}


fn print_arr(arr:[i32; 5]){
  println!("{:?}", arr);
  println!("{}", arr[0]);
}

fn print_arr2(arr:&[i32; 5]){
  println!("{:?}", arr); //会自动解引用
  println!("{}", arr[0]); //自动解引用
}

#[derive(Debug)]
struct Stru123 {
  name: String,
  age: i32
}
